home *** CD-ROM | disk | FTP | other *** search
-
- TITLE EDISK - INSTALLABLE DEVICE DRIVER FOR A HIGH MEMORY VIRTUAL DISK
- ;11/10/85
- ; This ram disk uses the 128K portion of memory above 640K be-
- ; ginning at segment D000:0000 and ending at F000:0000.
- ; The original code comes from the DOS 2.0 Technical Manual, later
- ; modified by Rex McAnally to allow variable sizes. (I have
- ; included his original notes below.)
- ; The code has been modified in accordence with the POWER USER
- ; column in PC Magazine, Oct. 15, 1985. It includes the following
- ; features:
- ; a. It will assemble with both versions 1 & 2 MACRO
- ; Assenbler
- ;
- ; b. The program initializes the 128K RAM to prevent the
- ; dreaded PARITY error (DOS won't do it)
- ;
- ; c. The contents of the Ram disk will survive a warm boot
- ; (Ctl-Alt-Del)
- ;
- ; You have to provide the 128K ram memory addressable at segment D000
- ; Note: This 128K was reserved for ROM based programs like those found
- ; for the PC jr. None are available for the PC/PC-XT so the
- ; memory space is normally unusable & wasted. It can't be added
- ; to DOS as it is'nt continuous with the 640K user's area.
- ;
- ; The easiest way to add this memory to your PC is to buy an IBM
- ; 64/256K Memory Expansion Option board, install 128K on it, and
- ; set its DIP switches for a start address of D000 like so:
- ;
- ; switch 1 2 3 4 5 6 7 8
- ; position off off on off off on off off
- ;
- ; Not all memory or combo memory boards will do. Most don't allow
- ; you to choose the absolute starting segment address.
- ;
- ; To use this program:
- ;
- ; 1. Assemble this program using the MACRO Assembler
- ;
- ; 2. Link the resultant .OBJ file using LINK (DOS utility)
- ;
- ; 3. Convert the resultant .EXE file to binary form using
- ; EXE2BIN (also a DOS utility), and name it EDISK.SYS
- ;
- ; 4. Copy the EDISK.SYS file to your BOOT/Root directory
- ;
- ; 5. Add DEVICE=EDISK.SYS as the **FIRST** line of your
- ; CONFIG.SYS file. It M-u-s-t be first as the program
- ; has to know whether it sees a first or a subsequent
- ; Boot. Some Devive drivers cause a double Boot and
- ; if they precede EDISK.SYS they will cause EDISK to
- ; think an initial cold Boot is a warm Boot. This
- ; screws up the Ram Disk data preserve function and
- ; will most likely cause your system to hang up.
- ;
- ; A driver that adds 64K above the 640K user area to DOS (IF you have
- ; Ram there), such as MEMM.SYS works OK as long as it follows the EDISK
- ; driver in CONFIG.SYS.
- ;
- ; I have marked the lines I modified with EM and those I added
- ; with EM-A. By now this code has been pretty well hacked and
- ; could stand some cleaning up, but it works fine as is. Feel free
- ; to clean it up or improve it further.
- ;
- ; ENJOY,
- ; Bill Wacker
- ;
- ;
- ;Rex McNally's unmodified notes follow:
- ;
- ; This was originally the virtual disk device contained in
- ; the DOS 2.0 manual (listing only).
- ;
- ; The code has been modified to allow a ram disk of more than
- ; 180k. This can be specified in 2 ways.
- ; (1). Changing the RAMDISK equate statment to the desired size in
- ; 1 K increments, reassembling, linking, using EXE2BIN,
- ; to convert to "com" file format. (see DOS 2.0 manual on
- ; device drivers.
- ; (2). Rename the "VDISK.COM" file to "VDISK.XXX",
- ; Using DEBUG you can modify the size by changing offsets
- ; 29-30 hex in the file. offset 29 = low order byte, 30 = h/o
- ; These 2 bytes contain the size in 1K increments.
- ;
- ; The current maximum limit is 512K (0200 hex).
- ;
- ; All modified lines of code have been labeled with <RM> comments.
- ; Please feel free to play with this, I am considering enhancing it
- ; to ask the operator for a size before completing the device
- ; installation.
- ; Rex McAnally
- ;
- PAGE
- CSEG SEGMENT PARA PUBLIC 'CODE'
- ;
- ;*** MACRO DEFINITIONS
- ;
- STATUS MACRO STATE,ERR,RC
- IFIDN <STATE>,<DONE>
- OR ES:WORD PTR SRH_STA_FLD[BX],0100H
- ENDIF
- IFIDN <STATE>,<BUSY>
- OR ES:WORD PTR SRH_STA_FLD[BX],0200H
- ENDIF
- IFIDN <ERR>,<ERROR>
- OR ES:WORD PTR SRH_STA_FLD[BX],1000H
- ENDIF
- IFNB <RC>
- OR ES:WORD PTR SRH_STA_FLD[BX],RC
- ENDIF
- ENDM
- ;
- ;***Equates
- ;
- ;***Size
- ;
- SECT EQU 512 ; size of a sector <RM>
- RAMDISK EQU 128 ; size of ramdisk in 1k increments <RM> <EM>
- FATSIZE EQU 1 ; # sect in 1 copy of fat <RM>
- ;
- ;***Read/Write
- ;
- SRH EQU 0 ;Static request header start
- SRH_LEN EQU 13 ; " " " length
- SRH_LEN_FLD EQU SRH ; " " " length field
- SRH_UCD_FLD EQU SRH+1 ; " " " unit code field
- SRH_CCD_FLD EQU SRH+2 ; " " " command code fld
- SRH_STA_FLD EQU SRH+3 ; " " " status field
- SRH_RES_FLD EQU SRH+5 ; " " " reserved area fld
- MD EQU SRH+SRH_LEN ;Media descriptor byte
- MD_LEN EQU 1 ; " " " length
- DTA EQU MD+MD_LEN ;Disk transfer address
- DTA_LEN EQU 4 ;DTA length
- COUNT EQU DTA+DTA_LEN ;Byte/Sector count
- COUNT_LEN EQU 2 ; " " length
- SSN EQU COUNT+COUNT_LEN ;Starting sector number
- SSN_LEN EQU 2 ; " " " length
- ;
- ;***Media check
- ;
- RET_BYTE EQU MD+MD_LEN ;Byte returned from driver
- ;
- ;***Build BPB
- ;
- BPBA_PTR EQU DTA+DTA_LEN
- BPBA_PTA_LEN EQU 4
- ;
- ;***Init
- ;
- UNITS EQU SRH+SRH_LEN
- UNITS_LEN EQU 1
- BR_ADDR_0 EQU UNITS+UNITS_LEN
- BR_ADDR_1 EQU BR_ADDR_0+2
- BR_ADDR_LEN EQU 4
- BPB_PTR_OFF EQU BR_ADDR_0+BR_ADDR_LEN
- BPB_PTR_SEG EQU BPB_PTR_OFF+2
- ;
- ;
- VDSK PROC FAR
- ASSUME CS:CSEG,ES:CSEG,DS:CSEG
- BEGIN:
- START EQU $
- ;
- ;***Special device header
- ;
- NEXT_DEV DD -1 ;Pointer to next device
- ATTRIBUTE DW 2000H ;Block device (NON-IBM FORMAT)
- STATEGY DW DEV_STATEGY ;Pointer to device stategy
- INTERRUPT DW DEV_INT ;Pointer to device interrupt handler
- DEV_NAME DB 1 ;Number of block devices
- DB 7 DUP(?) ;7 bytes of filler
- RH_OFF DW ? ;Request header offset
- RH_SEG DW ? ;Request header segment
- ;
- ;***BIOS parameter block
- ;
- BPB EQU $
- DW SECT ;Sector size <RM>
- DB 1 ;Sectors/allocation unit
- DW 1 ;Number of reserved sectors
- DB 2 ;Number of FATS
- DW 64 ;# of directory entries <RM>
- RAMSECT1 DW 256 ;Total number of sectors <EM>
- DB 0FEH ;Media descriptor
- FATSIZE1 DW FATSIZE ;# of sectors used by FAT<RM>
- BPB_PTR DW BPB ;BIOS parameter blk ptr array
- ;
- ;***Current virtual disk information
- ;
- DB 'SIZE' ; <RM>
- RAMSIZEK DW RAMDISK ; size in 1k increments <RM>
- RAMSIZEP DW RAMDISK*(1024/16) ; size in paragraphs <RM>
- ;
- TOTAL DW ? ;Total sectors to transfer
- VERIFY DB 0 ;Verify 1=YES, 0=NO
- START_SEC DW 0 ;Starting sector number
- VDISK_PTR DW 0 ;Starting sector of virtual disk
- USER_DTA DW ?,? ;Pointer to callers DTA <EM>
- BOOT_REC EQU $ ;Dummy DOS boot record
- DB 3 DUP(0) ;3 byte jump to boot code (not bootable)
- DB 'IBM 2.0'
- DW SECT ;Number of bytes in a sector <RM>
- DB 1 ;1 sector per allocation unit
- DW 1 ;1 reserved sector
- DB 2 ;2 FATS
- DW 64 ;Number of directory entries
- RAMSECT2 DW 256 ; total sectors in image <RM><EM>
- DB 0FEH ;Single sided 9 sector
- FATSIZE2 DW FATSIZE ;Number of sectors in FAT <RM>
- ;
- ;***Function table
- ;
- FUNTAB LABEL BYTE
- DW INIT ;Initialization
- DW MEDIA_CHECK ;Media check (block only)
- DW BUILD_BPB ;Build BPB
- DW IOCTL_IN ;IOCTL input
- DW INPUT ;Input (read)
- DW ND_INPUT ;Non destructive input no wait (ch only)
- DW IN_STAT ;Input status
- DW IN_FLUSH ;Input flush
- DW OUTPUT ;Output (write)
- DW OUT_VERIFY ;Output (write) with verify
- DW OUT_STAT ;Output status
- DW OUT_FLUSH ;Output flush
- DW IOCTL_OUT ;IOCTL output
- ;
- ;***Local procedures
- ;
- IN_SAVE PROC NEAR
- MOV AX,ES:WORD PTR DTA[BX] ;Save callers DTA
- MOV CS:USER_DTA,AX
- MOV AX,ES:WORD PTR DTA+2[BX]
- MOV CS:USER_DTA+2,AX
- MOV AX,ES:WORD PTR COUNT[BX]
- XOR AH,AH
- MOV CS:TOTAL,AX
- RET
- IN_SAVE ENDP
- ;
- ;
- CALC_ADDR PROC NEAR
- MOV AX,CS:START_SEC ;Get starting sector number
- MOV CX,SECT/16 ;Move 512 to CX segment style
- MUL CX ;Multiply to get actual sector
- MOV DX,CS:VDISK_PTR ;Get segment of virtual disk
- ADD DX,AX ;Add that seg to initial seg
- MOV DS,DX ;Save that as actual segment
- XOR SI,SI ;It's on a para boundary
- MOV AX,CS:TOTAL ;Total # of sectors to read
- MOV CX,SECT ;Bytes per sector <RM>
- MUL CX ;Multiply to get copy length
- OR AX,AX ;Check for greater than 64K
- JNZ MOVE_IT
- MOV AX,0FFFFH ;Move in for 64K
- MOVE_IT: XCHG CX,AX ;Move length to CX
- RET
- CALC_ADDR ENDP
-
-
- SECTOR_READ PROC NEAR
- CALL CALC_ADDR ;Calculate the starting sector
- MOV ES,CS:USER_DTA+2 ;Set dest (ES:DI) to point
- MOV DI,CS:USER_DTA ;**to callers DTA
- ;
- ;***Check for DTA wrap in case we came through via verify
- ;
- MOV AX,DI ;Get offset of DTA
- ADD AX,CX ;Add copy length to it
- JNC RC ;Carry flag=0, no wrap
- MOV AX,0FFFFH ;Max length
- SUB AX,DI ;Subtract DTA offset from max
- MOV CX,AX ;Use that as copy length to avoid wrap
- RC: REP MOVSB ;Do the read
- RET
- SECTOR_READ ENDP
-
-
- SECTOR_WRITE PROC NEAR
- CALL CALC_ADDR ;Calculate starting sector
- PUSH DS
- POP ES ;Establish addressability
- MOV DI,SI ;ES:DI point to disk
- MOV DS,CS:USER_DTA+2 ;DS:SI point to callers DTA
- MOV SI,CS:USER_DTA
- ;
- ;***Check for DTA wrap
- ;
- MOV AX,SI ;Move DTA offset to AX
- ADD AX,CX ;Add copy length to offset
- JNC WC ;Carry flag=0, no segment wrap
- MOV AX,0FFFFH ;Move in max copy length
- SUB AX,SI ;Subtract DTA offset from max
- MOV CX,AX ;Use as new copy length to avoid wrap
- WC: REP MOVSB ;Do the write
- RET
- SECTOR_WRITE ENDP
- PAGE
- ;
- ;***Device strategy
- ;
- DEV_STATEGY: MOV CS:RH_SEG,ES ;Save segment of request header ptr
- MOV CS:RH_OFF,BX ;Save offset of " " "
- RET
- ;
- ;***Device interrupt handler
- ;
- DEV_INT: CLD
- ;
- ;***Save state of machine
- ;
- PUSH DS
- PUSH ES
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- ;
- ;***Do branch according to function passed
- ;
- MOV AL,ES:[BX]+2 ;Get function byte
- ROL AL,1 ;Get offset into table
- LEA DI,FUNTAB ;Get address of function table
- XOR AH,AH
- ADD DI,AX
- JMP WORD PTR[DI]
- ;
- ;***Initialization
- ;
- INIT:
- MOV AX,CS:RAMSIZEK ; compute size in # sect <RM>
- CMP AX,171 ; <RM>
- JB INIT20 ; <RM>
- MOV CS:WORD PTR FATSIZE1,2 ; <RM>
- MOV CS:WORD PTR FATSIZE2,2 ; <RM>
- CMP AX,341 ; <RM>
- JB INIT20 ; <RM>
- MOV CS:WORD PTR FATSIZE1,3 ; <RM>
- MOV CS:WORD PTR FATSIZE2,3 ; <RM>
- INIT20: ; <RM>
- SHL AX,1 ; <RM>
- MOV CS:RAMSECT1,AX ; <RM>
- MOV CS:RAMSECT2,AX ; <RM>
- MOV CL,5 ; compute size in paragr <RM>
- SHL AX,CL ; <RM>
- MOV CS:RAMSIZEP,AX ; <RM>
- ; <RM>
- PUSH CS
- POP DX ;Current CS to DX
- LEA AX,CS:VDISK ;Get address of virtual disk
- MOV CL,4
- ROR AX,CL ;Divide by 16 (paragraph form)
- ADD DX,AX ;Add to current CS value
- MOV CS:VDISK_PTR,0D000H ;Save as start seg of vdisk <EM>
- ; MOV AX,CS:RAMSIZEP ;Add size of vdisk in para<RM><EM>
- ; ADD DX,AX ;**segment of virtual disk <EM>
- MOV ES:WORD PTR BR_ADDR_0[BX],0
- MOV ES:BR_ADDR_1[BX],DX ;Make that the break address
- MOV ES:BYTE PTR UNITS[BX],1 ;Number of diskette units
- LEA DX,BPB_PTR ;Get addr of BPB ptr array
- MOV ES:BPB_PTR_OFF[BX],DX ;Save offset in data packet
- MOV ES:BPB_PTR_SEG[BX],CS ;Save segment in data packet
-
- PUSH DS ;Save DS <EM-A>
- MOV AX,40H ;BIOS data segment <EM-A>
- MOV DS,AX ;Set up segment register <EM-A>
- CMP WORD PTR DS:[0072H],1234H ;Check reset mode <EM-A>
- POP DS ;Restore DS <EM-A>
- JNZ COLD_START ;Initialize Vdisk <EM-A>
- JMP HOT_START ;Skip if boot from keyboard<EM-A>
-
-
- COLD_START: ; Initialize memory to avoid PARITY errors <EM-A>
- SUB AX,AX ;Byte to write (null) <EM-A>
- MOV ES,CS:VDISK_PTR ;Get start addr of 1st 64K sector
- MOV CX,8000H ;Number of bytes to write <EM-A>
- REP STOSW ;Repeat no. of times in CX <EM-A>
- MOV CX,ES ;Move to next sector by <EM-A>
- ADD CX,1000H ;adding 1000H to ES <EM-A>
- MOV ES,CX ;New start addr at E000H <EM-A>
- MOV CX,8000H ;Reset CX counter to 8000H <EM-A>
- REP STOSW ;Repeat write in second sect<EM-A>
- MOV ES,CS:VDISK_PTR ;Restore addr to 1st seg <EM-A>
-
- XOR DI,DI ;Zero out DI (Boot record)
- LEA SI,BOOT_REC ;Address of boot record
- MOV CX,24
- REP MOVSB ;Copy 24 bytes of boot record
- MOV CS:WORD PTR START_SEC,1
- MOV AX,FATSIZE1 ; <RM>
- MOV CS:WORD PTR TOTAL,AX ; <RM>
- CALL CALC_ADDR ;Calc addr of logical sect 1
- PUSH DS
- POP ES
- MOV DI,SI ;Move that address to ES:DI
- XOR AL,AL
- REP STOSB ;Zero out FAT area
- MOV DS:BYTE PTR[SI],0FEH ;Set the first FAT entry
- MOV DS:BYTE PTR 1[SI],0FFH
- MOV DS:BYTE PTR 2[SI],0FFH
- PUSH DS ;Save pointer to FAT on
- PUSH SI ;**the stack
- MOV AX,CS:WORD PTR START_SEC ; <RM>
- ADD AX,CS:WORD PTR TOTAL ; <RM>
- MOV CS:WORD PTR START_SEC,AX ; <RM>
- ;DEL MOV CS:WORD PTR TOTAL,2 <RM>
- CALL CALC_ADDR ;Calc addr of logical sect 3
- PUSH DS
- POP ES
- MOV DI,SI ;Move that address to ES:DI
- POP SI
- POP DS ;Restore addr of 1st entry
- REP MOVSB ;Copy first FAT to second FAT
- MOV AX,CS:WORD PTR START_SEC ; <RM>
- ADD AX,CS:WORD PTR TOTAL ; <RM>
- MOV CS:WORD PTR START_SEC,AX ; <RM>
- ;DEL MOV CS:WORD PTR START_SEC,5 <RM>
- MOV CS:WORD PTR TOTAL,4
- CALL CALC_ADDR ;Calc addr of LS 5 (start dir
- XOR AL,AL
- PUSH DS
- POP ES ;Set up ES:DI to point to it
- XOR DI,DI
- REP STOSB ;Zero out directory
- MOV ES,CS:RH_SEG ;Restore ES:BX to req header
- MOV BX,CS:RH_OFF
- STATUS DONE,NOERROR,0 ;Set status done (noerror)
-
- LEA DX,COLD_MESSAGE ;Choose initialize msg <EM-A>
- JMP SHORT MESSAGE ;Go display it <EM-A>
- COLD_MESSAGE DB "Hi-RAM disk installed.",13,"$" ; <EM-A>
- HOT_MESSAGE DB "Hi RAM disk preserved.",13,"$" ; <EM-A>
- HOT_START: LEA DX,HOT_MESSAGE ;Choose preserve msg <EM-A>
- MESSAGE: PUSH CS ;Current segment <EM-A>
- POP DS ;Set DS to it <EM-A>
- MOV AH,9 ;DOS print string call <EM-A>
- INT 21H ;Print the string <EM-A>
-
- JMP EXIT
- ;
- ;***Media check
- ;
- MEDIA_CHECK: MOV ES:BYTE PTR RET_BYTE[BX],1
- STATUS DONE,NOERROR,0 ;turn on the done bit
- JMP EXIT
- ;
- ;***Build BIOS parameter block
- ;
- BUILD_BPB: PUSH ES ;Save SRH segment
- PUSH BX ;Save SRH offset
- MOV CS:WORD PTR START_SEC,0
- MOV CS:WORD PTR TOTAL,1
- CALL CALC_ADDR ;Calc addr of 1st sector
- PUSH CS
- POP ES
- LEA DI,BPB ;Addr of BIOS parameter block
- ADD SI,11
- MOV CX,13 ;Length of BPB
- REP MOVSB
- POP BX ;Restore offset of SRH
- POP ES ;Restore segment of SRH
- LEA DX,BPB ;Get BPB array pointer
- MOV ES:BPBA_PTR[BX],DX ;Save ptr to BPB table
- MOV ES:BPBA_PTR+2[BX],CS
- MOV ES:DTA[BX],DX ;Offset to sector buffer
- MOV ES:DTA+2[BX],CS
- STATUS DONE,NOERROR,0
- JMP EXIT
- ;
- ;***The following entries are not supported by this device
- ;
- IOCTL_IN:
- IOCTL_OUT:
- ND_INPUT: ;Non destructive input no wait (ch only)
- IN_STAT: ;Input status " "
- IN_FLUSH: ;Input flush
- OUT_STAT: ;Output status
- OUT_FLUSH: ;Output flush
- ;
- ;***Disk read
- ;
- INPUT: CALL IN_SAVE ;Call the initial save rtn
- MOV AX,ES:WORD PTR SSN[BX] ;Set starting sector number
- MOV CS:START_SEC,AX ;Save starting sector number
- MOV AX,ES:WORD PTR COUNT[BX]
- MOV CS:TOTAL,AX ;Save # sectors to transfer
- CALL SECTOR_READ ;Read in that many sectors
- MOV BX,CS:RH_OFF ;Restore ES:BX as req header
- MOV ES,CS:RH_SEG
- STATUS DONE,NOERROR,0 ;Set status word (done, noerr
- JMP EXIT
- ;
- ;***Disk write
- ;
- OUTPUT: CALL IN_SAVE ;Output (write)
- MOV AX,ES:WORD PTR SSN[BX] ;Get starting sector number
- MOV CS:START_SEC,AX ;Set " " "
- MOV AX,ES:WORD PTR COUNT[BX]
- MOV CS:TOTAL,AX ;Save total sectors to write
- CALL SECTOR_WRITE
- MOV BX,CS:RH_OFF ;Restore ES:BX as req header
- MOV ES,CS:RH_SEG
- CMP CS:BYTE PTR VERIFY,0 ;Write verify set
- JZ NO_VERIFY ;No, no write verify
- MOV CS:BYTE PTR VERIFY,0 ;Reset verify indicator
- JMP INPUT
- NO_VERIFY: STATUS DONE,NOERROR,0 ;Set status done, no error
- JMP EXIT
- OUT_VERIFY: MOV CS:BYTE PTR VERIFY,1 ;Set verify flag
- JMP OUTPUT ;Branch to output routine
- ;
- ;***Common exit
- ;
- EXIT: POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- RET
- ;
- ;
- E_O_P:
- ;***Macro to align the virtual disk on a paragraph boundary
- IF ($-START) MOD 16
- ORG ($-START)+16-(($-START) MOD 16)
- ENDIF
- VDISK EQU $
- VDSK ENDP
- CSEG ENDS
- END BEGIN